/* CPP Assignemnt 3 (COSC1152-2011-S2)
 * Elliott O'Dea-Joyce s3074110@student.rmit.edu.au
 * Ross Nye s9455459@student.rmit.edu.au
 */

#include "graph_strat.h"
#include "tri.h"
#include "utils.h"

GraphStrat::~GraphStrat()
{
	delete v;
	delete e;
	delete w;
}

// sets up the 3 vectors required for the graph algos and either
// loads vectors from file or generates the vectors
void GraphStrat::setup_vertex(char* setup_string)
{
#if DEBUG
  std::cout << "Seting up vertex using " << setup_string << std::endl;
#endif
  
	v = new std::vector<V>();
	e = new std::vector<E>();
	w = new std::vector<float>();
	
	// if setup_string starts with -g: pass in number and generate
	// otherwise load from file
	if(*setup_string == '-' && setup_string[1] == 'g' && setup_string[2] == ':')
		generate_vertex(setup_string+3);
	else
		loadfile(setup_string);
}


// generate vertex in graph using algorithm for original sample solution
void GraphStrat::generate_vertex(char* num_string)
{
#if DEBUG
	std::cout << "Generating vertex of size " << num_string << std::endl;
#endif
	int size = toInt(num_string);
	
	if (size < 3)
		throw std::runtime_error("Size for vertex genratation does not make sense");


	srand(0);
	for (int i = 0; i < size; i++)
	{
		float x = ((float) rand() / (float) RAND_MAX);
		float y = ((float) rand() / (float) RAND_MAX);

		v->push_back(V(x,y));
	}
	numVertex = v->size();
}


// populates the vertex from the file supplied
void GraphStrat::loadfile(char* filename)
{
#if DEBUG
	std::cout << "Loading from file " << filename << std::endl;
#endif
	std::ifstream fin(filename);
	if (!fin.is_open())
		throw std::runtime_error("Unable to open file for reading ");
	
	// read the number of vertex from the first line
	fin >> numVertex;
#if DEBUG
	std::cout << "numVertex= " << numVertex << std::endl;
	int point = 0;
#endif
	
	// until there is no more data read the file
	float pX, pY;
	while(!fin.eof())
	{
		fin >> pX;
		fin >> pY;
		if(!fin.eof())
		{
			v->push_back(V(pX, pY));
#if DEBUG
			std::cout << " point= " << point << " x= " << pX;
			std::cout << " y= " << pY << std::endl;
			point++;
#endif
		}
	}
	fin.close();
#if DEBUG
	std::cout << "vertex vector size = " << v->size() << std::endl;
#endif
	if((unsigned int)numVertex != v->size())
		throw std::runtime_error("Vertex size and stated size do not match");
};




// creates the Delaunay graph - string can be -g:999 or filename
void DelaunayGraph::create(char* setup_string)
{
#if DEBUG
	std::cout << "Creating delaunay graph"  << std::endl;
#endif

	setup_vertex(setup_string);	
	triangulate(*v, *e, *w);
	
#if DEBUG
	std::cout << "Created delaunay graph, vectors " << v->size() << std::endl;
	std::cout << "Created delaunay graph, edges " << e->size() << std::endl;
	std::cout << "Created delaunay graph, weights " << w->size() << std::endl;
#endif

};

// creates a complete graph - string can be -g:999 or filename
void CompleteGraph::create(char* setup_string)
{
#if DEBUG
	std::cout << "Creating complete graph"  << std::endl;
#endif

	setup_vertex(setup_string);

	// setup edges and weights by walking vertex and pairing them up
	for(int i = 0, j = 0; j < numVertex - 1; j++)
	{
		for(int k = 0; k < numVertex; k++)
		{
			// if statement only adds one edge per <A,B> pair A-B, not B-A
			if(j < k)
			{
				e->push_back(E(j,k));
				w->push_back(pow(v->at(j).first - v->at(k).first, 2) + 
						pow(v->at(j).second - v->at(k).second, 2));
#if DEBUG
				//std::cout << " i= " << i << " j= " << j << " k= " << k << std::endl;
#endif
				i++;
			}			
		}
	}
#if DEBUG
	std::cout << "Created complete graph, vectors " << v->size() << std::endl;
	std::cout << "Created complete graph, edges " << e->size() << std::endl;
	std::cout << "Created complete graph, weights " << w->size() << std::endl;
#endif
};



